package universum.util;

import java.util.HashMap;
import java.util.Map;

public class Statistics {
    private static Statistics _instance = new Statistics();
    private ioUtility io = ioUtility.getInstance();
    public int completedRoundsCount;

    public enum AggregationType {
        sum, max, min, avg
    }

    private Map<AggregationType, Map<String, Float>> report;

    public static Statistics getInstance() {
        return _instance;
    }

    private Statistics() {
        report = new HashMap<AggregationType, Map<String, Float>>();
        for (AggregationType a : AggregationType.values()) report.put(a, new HashMap<String, Float>());
    }

    public void addReport(String fieldName, Integer fieldValue, AggregationType fieldAggrefationType) {
        addReport(fieldName, Float.valueOf(fieldValue.toString()), fieldAggrefationType);
    }

    public void PublishReport() {
        Map<String, Float> reportTable;
        io.writelnReport("rounds count = " + completedRoundsCount);
        for (AggregationType a : AggregationType.values()) {
            reportTable = report.get(a);
            if (reportTable.size() > 0) {
                io.writelnReport("aggregation type: " + a.name());
                for (Map.Entry<String, Float> pair : reportTable.entrySet()) {
                    //io.writeDebug(pair.getKey() + " = " + pair.getValue());
                    io.writelnReport(pair.getKey() + " = " + pair.getValue());
                }
                io.writelnReport("________________");
            }
        }
    }

    public void PublishForExcel()
    {
        Map<String, Float> reportTable = report.get(AggregationType.avg);
        //io.writelnReport("rounds count = " + completedRoundsCount);
        /*for (AggregationType a : AggregationType.values()) {
            reportTable = report.get(a);
            if (reportTable.size() > 0) {
                io.writelnReport("aggregation type: " + a.name());
                for (Map.Entry<String, Float> pair : reportTable.entrySet()) {
                    //io.writeDebug(pair.getKey() + " = " + pair.getValue());
                    io.writelnReport(pair.getKey() + " = " + pair.getValue());
                }
                io.writelnReport("________________");
            }
        } */
        String m = GameIterator.getInstance().imitationParams.gameInfo.customArgs.get("mass");
        String avgm = reportTable.get("average mass: ").toString();
        String maxm = report.get(AggregationType.max).get("maximum mass: ").toString();
        String minm = report.get(AggregationType.min).get("minimum mass: ").toString();
        io.writelnReport(m + " " + avgm + " " + maxm + " " + minm);
    }

    public void addReport(String fieldName, Float fieldValue, AggregationType fieldAggregationType) {
        //System.out.println(fieldName + " = " + fieldValue.toString());
        Map<String, Float> reportTable = report.get(fieldAggregationType);
        if (reportTable.containsKey(fieldName)) {
            Float curValue = reportTable.get(fieldName), newValue = curValue;
            switch (fieldAggregationType) {
                case sum:
                    newValue += fieldValue;
                    break;
                case max:
                    if (curValue < fieldValue) newValue = fieldValue;
                    break;
                case min:
                    if (curValue > fieldValue) newValue = fieldValue;
                    break;
                case avg:
                    newValue += fieldValue;
                    break;
            }
            if (!curValue.equals(newValue)) reportTable.put(fieldName, newValue);
            //if (curValue != newValue) reportTable.put(fieldName,  newValue);
        } else {
            reportTable.put(fieldName, fieldValue);
            //System.out.println("first add of " + fieldName);
        }
    }

    public void PrepareReport() {
        Map<String, Float> reportTable;
        reportTable = report.get(AggregationType.avg);
        for (Map.Entry<String, Float> pair : reportTable.entrySet())
            pair.setValue(pair.getValue() / completedRoundsCount);
    }
}
